package breakthrough.AlphaBetaPlayer;

public class TimeManager {
	
	private static final int AVERAGE = 190;
	private static final int SPREAD = 85;
	private static final int MULTIPLIER = 4000;
	private static final int BASE = 2;
	private static final double SQRT_TWO_PI = 2.50663;
	private static final double E = 2.71828;
	private static final double TIME_LEFT = 5;
	
	private Timer timer;
	private MonitoringThread monitoringThread;
	private double timeApproximation;
	
	public TimeManager(Timer timer, int numOurMoves, Object monitor) {
		this.timer = timer;
		this.timeApproximation = this.getTimeApproximation(this.timer.getTimeRemaining(), numOurMoves);
		this.monitoringThread = new MonitoringThread(this.timeApproximation, monitor);
		if (this.timeApproximation > 0) {
			this.monitoringThread.start();
		}
		
	}
	
	public double getTimeApproximation(double timeRemaining, int numOurMoves) {
		if (timeRemaining < TIME_LEFT) {
			return 0;
		}
		return this.getTimeApproximationHelper(AVERAGE, SPREAD, MULTIPLIER, this.timer.getInitialTime() - timeRemaining);
	}
	
	public double getTimeApproximation() {
		return this.timeApproximation;
	}
	
	private double getTimeApproximationHelper(double average, double spread, double multiplier, double timeUsed) {
		double inner = (timeUsed - AVERAGE)/SPREAD;
		double power = -0.5 * inner * inner;
		return (multiplier/(spread*SQRT_TWO_PI))*Math.pow(E, power) + BASE;
	}
	
	private class MonitoringThread extends Thread {
		private double timeApproximation;
		private Object monitor;
		
		public MonitoringThread(double timeApproximation, Object monitor) {
			super();
			this.timeApproximation = timeApproximation;
			this.monitor = monitor;
		}
		
		
		@Override
		public void run() {
			double time = 0;
			double lastTime = ((double) System.currentTimeMillis())/1000;
			
			while(time < timeApproximation) {
				double curTime = ((double) System.currentTimeMillis())/1000;
				time += curTime - lastTime;
				lastTime = curTime;
			}
			
			synchronized(this.monitor) {
				if (this.monitor != null) {
					this.monitor.notify();
				}
			}
		}
	}
}
